package funcUtils

import (
	"fmt"
	"go-demo-2025/common"
	"reflect"
	"strconv"
	"strings"
	"time"
)

// 结构体转为slice
func StructToSlice(data any) []string {
	v := reflect.ValueOf(data)
	ss := make([]string, v.NumField())
	for i := range ss {
		ss[i] = fmt.Sprintf("%v", v.Field(i))
	}

	return ss
}

func GetStructTag(data any) []string {
	t := reflect.TypeOf(data)
	var result []string
	for i := 0; i < t.NumField(); i++ {
		field := t.Field(i)
		jsonTag := field.Tag.Get("json")
		//fmt.Printf("Field: %s, Tag: %s\n", field.Name, jsonTag)
		result = append(result, jsonTag)
	}
	return result
}

// 结构体转为Map[string]interface{}
func StructToMap(in any, tagName string) (map[string]string, error) {
	out := make(map[string]string)

	v := reflect.ValueOf(in)
	if v.Kind() == reflect.Ptr {
		v = v.Elem()
	}

	if v.Kind() != reflect.Struct { // 非结构体返回错误提示
		return nil, fmt.Errorf("ToMap only accepts struct or struct pointer; got %T", v)
	}

	t := v.Type()
	// 遍历结构体字段
	// 指定tagName值为map中key;字段值为map中value
	for i := 0; i < v.NumField(); i++ {
		fi := t.Field(i)
		tagValue := fi.Tag.Get(tagName)
		if tagValue != "" {
			//out[tagValue] = v.Field(i).Interface()
			//fmt.Println(tagValue, " ==> ", fi.Type.String())
			switch fi.Type.String() {
			case "int", "int8", "int16", "int32", "int64":
				out[tagValue] = fmt.Sprintf("%d", v.Field(i).Int())
			case "float32", "float64":
				out[tagValue] = fmt.Sprintf("%f", v.Field(i).Float())
			case "string":
				out[tagValue] = v.Field(i).String()
			case "bool":
				out[tagValue] = fmt.Sprintf("%v", v.Field(i).Bool())
			case "time.Time":
				timeStr := fmt.Sprintf("%v", v.Field(i).Interface())
				if strings.Contains(timeStr, "0001-01-01 00:00:00") {
					out[tagValue] = ""
				} else {
					out[tagValue] = common.FormatTimestamp(v.Field(i).Interface().(time.Time).Unix())
				}
			default:
				out[tagValue] = fmt.Sprintf("%v", v.Field(i).Interface())
			}
		}
	}
	return out, nil
}

// 通过反射将嵌套结构体转换为一维 map
func ConvertToFlatMap(obj interface{}, prefix string) map[string]interface{} {
	val := reflect.ValueOf(obj)
	result := make(map[string]interface{})

	// 递归处理结构体
	flatten(val, prefix, &result)

	return result
}

// 递归处理结构体
func flatten(val reflect.Value, prefix string, result *map[string]interface{}) {
	// 如果当前值是结构体类型
	if val.Kind() == reflect.Struct {
		for i := 0; i < val.NumField(); i++ {
			field := val.Type().Field(i)
			fieldValue := val.Field(i)

			// 检查字段是否导出
			if field.PkgPath == "" {
				//newPrefix := field.Name
				newPrefix := field.Tag.Get("json")
				// 递归处理子字段
				flatten(fieldValue, newPrefix, result)
			}
		}
	} else if val.Kind() == reflect.Slice {
		// 如果当前值是切片类型
		for i := 0; i < val.Len(); i++ {
			elem := val.Index(i)

			// 递归处理切片中的元素
			newPrefix := strconv.Itoa(i)
			flatten(elem, newPrefix, result)
		}
	} else {
		// 如果当前值不是结构体或切片类型
		(*result)[prefix] = val.Interface()
	}
}
